/*
 *     KRTS 网络服务器 - 内核程序
 *     时间： 2024-8-10
 *     版本： 0.1
 *     代码规范： Google 开源项目风格
 *     版权所有： 山东易码智能科技股份有限公司
 */

#include "Base/SharedData.h"

SharedData *kernel_data_ {nullptr};
KSSocketAddr remote_addr_;                       // 远程地址
int64 send_time_ {0};                             // 发送时间
int64 last_jitter_time_ {0};                      // 上次抖动
int send_count_ {0};

/* 套接字回调函数 */
KSError __stdcall SocketCallBack(void * /*pArgs*/, void *context);

extern "C" KSError __declspec(dllexport) __stdcall InitKernel(void *args, void * /*pContext*/)
{
    KS_printK("-------------- InitKernel \n");
    kernel_data_ = static_cast<SharedData *>(args);

    /* 为传入数据创建管道。这将是一个消息管道 */
    KSError error = KS_createPipe(&kernel_data_->pipe_handle, "NetworkUdpServerPipe", 1, BUFFER_SIZE * 4, KS_INVALID_HANDLE, KSF_MESSAGE_PIPE);
    if (error != KS_OK) { return error; }

    /* 创建接收事件。 */
    error = KS_createEvent(&kernel_data_->receive_event_handle, "UdpServerReceiveEvent", KSF_NO_FLAGS);
    if (error != KS_OK) { return error; }

    // 为了对套接字上的事件做出反应，我们使用带有 KSF_DIRECT_EXEC 的回调。
    error = KS_createCallBack(&kernel_data_->socket_call_back, SocketCallBack, nullptr, KSF_DIRECT_EXEC, 0);
    if (error != KS_OK) { return error; }

    /* 打开网络适配器 */
    error = KS_openNetworkAdapter(&kernel_data_->adapter_handle, kernel_data_->device_name, nullptr, KSF_NO_FLAGS);
    if (error != KS_OK) { return error; }

    /* 网络将配置为使用在用户空间的应用程序中指定的 IP 地址、子网和网关。 */
    error = KS_execNetworkCommand(kernel_data_->adapter_handle, KS_NETWORK_SET_IP_CONFIG, &kernel_data_->ip_config, KSF_NO_FLAGS);
    if (error != KS_OK) { return error; }

    /* 在端口上创建一个 Udp 服务器套接字。 */
    KSSocketAddr socket_addr = {0};
    socket_addr.family = KS_FAMILY_IPV4;
    socket_addr.port = KS_htons(kernel_data_->port_config);
    *socket_addr.address = kernel_data_->ip_config.localAddress;

    error = KS_openSocket(&kernel_data_->socket_handle, kernel_data_->adapter_handle, &socket_addr, KS_PROTOCOL_UDP, KSF_ACCEPT_BROADCAST);
    if (error != KS_OK) { return error; }

    // 设置套接字的最大传输单位 （MTU）。
    int mtu = 1024;
    error = KS_execSocketCommand(kernel_data_->socket_handle, KS_SOCKET_SET_MTU, &mtu,KSF_NO_FLAGS);
    if (error != KS_OK) { return error; }

    /* 安装数据接收回调 */
    error = KS_installSocketHandler(kernel_data_->socket_handle, KS_SOCKET_RECV, kernel_data_->socket_call_back, KSF_NO_FLAGS);
    if (error != KS_OK) { return error; }

    // 初始化远程地址
    remote_addr_.family = KS_FAMILY_IPV4;
    remote_addr_.port = KS_htons(kernel_data_->port_config);
    *remote_addr_.address = kernel_data_->remote_addr;

    return KS_OK;
}

extern "C" KSError __declspec(dllexport) __stdcall ExitKernel(void * /*pArgs*/, void * /*pContext*/)
{
    KS_printK("-------------- ExitKernel \n");
    if (kernel_data_ == nullptr) { return KSERROR_FUNCTION_NOT_AVAILABLE; }
    KS_installSocketHandler(kernel_data_->socket_handle, KS_SOCKET_RECV, KS_INVALID_HANDLE, KSF_NO_FLAGS);
    /* 关闭套接字。 */
    KS_closeSocket(kernel_data_->socket_handle);
    /* 关闭网络适配器。 */
    KS_closeNetwork(kernel_data_->adapter_handle,KSF_NO_FLAGS);
    /* 移除回调。 */
    KS_removeCallBack(kernel_data_->socket_call_back);
    /*关闭事件 */
    KS_closeEvent(kernel_data_->receive_event_handle);
    /* 删除消息管道 */
    KS_removePipe(kernel_data_->pipe_handle);

    return KS_OK;
}

extern "C" __declspec(dllexport) KSError __stdcall SendBufferContent(void * /*pArgs*/, void * /*pContext*/)
{
    KS_printK("-------------- SendBufferContent \n");

    if (kernel_data_->send_length != 0)
    {
        for (int i = 1; i < 255; i++)
        {
            if (i == 181){continue; }

            KS_printK("-------------- %d \n",i);
            KSSocketAddr remote_addr;                       // 远程地址
            remote_addr.family = KS_FAMILY_IPV4;
            remote_addr.port = KS_htons(kernel_data_->port_config);
            uint addr;
            KS_makeIPv4(&addr, 192, 168, 0, i);
            *remote_addr.address = addr;

            KS_sendToSocket(kernel_data_->socket_handle, &remote_addr, kernel_data_->send_buffer, kernel_data_->send_length, nullptr,KSF_NO_FLAGS);
            KS_sendToSocket(kernel_data_->socket_handle, &remote_addr, "\r\n", 2, nullptr, KSF_NO_FLAGS);
        }

        // 记录发送时间
        //KS_getClock(&send_time_,KS_CLOCK_MEASURE_HIGHEST);
        // KSError error = KS_sendToSocket(kernel_data_->socket_handle, &remote_addr_, kernel_data_->send_buffer, kernel_data_->send_length, nullptr,
        //     KSF_NO_FLAGS);
        // if (error != KS_OK) { return error; }
        //
        // error = KS_sendToSocket(kernel_data_->socket_handle, &remote_addr_, "\r\n", 2, nullptr, KSF_NO_FLAGS);
        // if (error != KS_OK) { return error; }

        // 计算抖动
        int64 rec_time;
        KS_getClock(&rec_time,KS_CLOCK_MEASURE_HIGHEST);

        if (send_count_ == 0)
        {
            send_time_ = rec_time;
            send_count_++;
            return KS_OK;
        }

        int64 jitter_time = rec_time - send_time_;
        send_time_ = rec_time;

        // 取绝对值
        int64 diff_tamp = jitter_time - last_jitter_time_ > 0 ? jitter_time - last_jitter_time_ : last_jitter_time_ - jitter_time;

        if (send_count_ == 1)
        {
            last_jitter_time_ = jitter_time;
            send_count_++;
            return KS_OK;
        }

        KS_convertClock(&diff_tamp,KS_CLOCK_MEASURE_HIGHEST,KS_CLOCK_MACHINE_TIME,KSF_NO_FLAGS);
        const int64 temp = diff_tamp;
        KS_printK("--- jitter_time: %d", temp);
        // 计算抖动保留最大值最小值，并进行分类
        if (temp / US < 9) // 单位 us
        {
            kernel_data_->jitter_data.classes[temp / US]++;
        }
        else
        {
            kernel_data_->jitter_data.classes[9]++;
        }

        if (kernel_data_->jitter_data.max_value < temp)
        {
            kernel_data_->jitter_data.max_value = temp;
        }

        if (kernel_data_->jitter_data.min_value > temp)
        {
            kernel_data_->jitter_data.min_value = temp;
        }
        kernel_data_->jitter_data.count++;

        last_jitter_time_ = jitter_time;
    }

    return KS_OK;
}

KSError __stdcall SocketCallBack(void * /*pArgs*/, void */* context */)
{
    KS_printK("-------------- SocketCallBack \n");

    KSError error;
    int length;

    do
    {
        byte read_buffer[BUFFER_SIZE];

        // 接收数据
        error = KS_recvFromSocket(kernel_data_->socket_handle, &remote_addr_, read_buffer, BUFFER_SIZE, &length, KSF_NO_FLAGS);
        if (error && KSERROR_CODE(error) != KSERROR_NO_DATA_AVAILABLE) { return error; }

        if (error == KS_OK)
        {
            error = KS_putPipe(kernel_data_->pipe_handle, read_buffer, length, nullptr,KSF_NO_FLAGS);
            KS_setEvent(kernel_data_->receive_event_handle);
        }
    } while (error == KS_OK);

    return KS_OK;
}

#pragma pack(push, 8)
#include <windows.h>
#pragma pack(pop)

BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD reason, LPVOID pReserved)
{
    return TRUE;
}
